/****************************************************************************
 * Copyright (C) 2009-2011 Dimok
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ****************************************************************************/
#include "gui_tooltip.h"
#include "../Themes/CTheme.h"
#include "../TextOperations/FreeTypeGX.h"

/**
 * Constructor for the Object class.
 */
GuiTooltip::GuiTooltip(const char *t)
	: cutBoundsRect(0xBADBABE, 0xBADBABE, 0xBADBABE, 0xBADBABE)
{
	InternalInit();
	
	SetText(t);
}

GuiTooltip::GuiTooltip(const wchar_t *t)
	: cutBoundsRect(0xBADBABE, 0xBADBABE, 0xBADBABE, 0xBADBABE)
{
	InternalInit();
	
	SetText(t);
}

GuiTooltip::GuiTooltip(std::string t)
	: cutBoundsRect(0xBADBABE, 0xBADBABE, 0xBADBABE, 0xBADBABE)
{
	InternalInit();
	
	SetText(t);
}

GuiTooltip::GuiTooltip(std::wstring t)
	: cutBoundsRect(0xBADBABE, 0xBADBABE, 0xBADBABE, 0xBADBABE)
{
	InternalInit();
	
	SetText(t);
}

GuiTooltip::~GuiTooltip()
{
	if(text)
		delete text;

	delete leftImage;
	delete tileImage;
	delete rightImage;

	Resources::Remove(tooltipLeft);
	Resources::Remove(tooltipTile);
	Resources::Remove(tooltipRight);
}

void GuiTooltip::InternalInit()
{
	xoffset = 0;
	yoffset = 0;
	zoffset = 0;
	width = 0;
	height = 0;
	alpha = 255;
	state = STATE_DEFAULT;
	stateChan = -1;
	parentElement = NULL;
	visible = false;
	yoffsetDyn = 0;
	xoffsetDyn = 0;
	alphaDyn = -1;
	
	MaxWidth = 0;
	text = NULL;
	FontSize = 22;
	color = thColor("r=0 g=0 b=0 a=255 - tooltip default text color");
	
	tooltipLeft = Resources::GetImageData("tooltip_left.png");
	tooltipTile = Resources::GetImageData("tooltip_tile.png");
	tooltipRight = Resources::GetImageData("tooltip_right.png");
	leftImage = new GuiImage(tooltipLeft);
	tileImage = new GuiImage(tooltipTile);
	rightImage = new GuiImage(tooltipRight);

	height = leftImage->GetHeight();

	leftImage->SetParent(this);
	tileImage->SetParent(this);
	rightImage->SetParent(this);
	
	alignment = (ALIGN_LEFT | ALIGN_TOP);
	
	effects = EFFECT_FADE;
	effectAmount = 20;
	effectTarget = 0;
}

void GuiTooltip::SetText(const char * t)
{
	if(!t)
		return;
	
	SetText(charToWideChar(t));
}

void GuiTooltip::SetText(const wchar_t * t)
{
	if(text)
		delete text;
	text = NULL;

	int tile_cnt = 0;
	if(t)
	{
		text = new GuiText(t, FontSize, color);
		text->SetParent(this);
		text->SetAlignment(ALIGN_CENTER | ALIGN_MIDDLE);
		
		if(MaxWidth > 0)
		{
			text->SetMaxWidth(MaxWidth, SCROLL_HORIZONTAL);
			tile_cnt = (int) ((float) (std::min(MaxWidth, text->GetTextWidth())-12) / (float) tileImage->GetWidth());
		}
		else
			tile_cnt = (int) ((float) (text->GetTextWidth()-12) / (float) tileImage->GetWidth());
		
		if(tile_cnt < 0)
			tile_cnt = 0;
	}
	tileImage->SetPosition(leftImage->GetWidth(), 0);
	tileImage->SetTileHorizontal(tile_cnt);
	rightImage->SetPosition(leftImage->GetWidth() + tile_cnt * tileImage->GetWidth(), 0);
	width = leftImage->GetWidth() + tile_cnt * tileImage->GetWidth() + rightImage->GetWidth();
}

void GuiTooltip::SetMaxWidth(int maxwidth)
{
	MaxWidth = maxwidth;

	if(text)
	{
		std::wstring wText(text->GetText());
		SetText(wText);
	}
}

void GuiTooltip::SetFontSize(int size)
{
	FontSize = size;

	if(text)
	{
		std::wstring wText(text->GetText());
		SetText(wText);
	}
}

void GuiTooltip::SetColor(GXColor c)
{
	color = c;

	if(text)
	{
		std::wstring wText(text->GetText());
		SetText(wText);
	}
}

void GuiTooltip::Show()
{
	if(!visible)
	{
		SetEffect(EFFECT_FADE, 20);
		visible = true;
	}
}

void GuiTooltip::Hide()
{
	if(visible)
		SetEffect(EFFECT_FADE, -20);
}

void GuiTooltip::SetState(int s, int c)
{
	state = s;
	stateChan = c;
}

int GuiTooltip::GetLeft()
{
	int pWidth = 0;
	int pLeft = 0;

	if(parentElement)
	{
		pWidth = parentElement->GetWidth();
		pLeft = parentElement->GetLeft();
	}

	pLeft += xoffsetDyn;

	int x = pLeft;

	if(alignment & ALIGN_CENTER)
	{
		x = pLeft + (pWidth/2) - (width/2);
	}
	else if(alignment & ALIGN_RIGHT)
	{
		x = pLeft + pWidth - width;
	}

	return x + xoffset;
}

int GuiTooltip::GetTop()
{
	int pHeight = 0;
	int pTop = 0;

	if(parentElement)
	{
		pHeight = parentElement->GetHeight();
		pTop = parentElement->GetTop();
	}

	pTop += yoffsetDyn;

	int y = pTop;

	if(alignment & ALIGN_MIDDLE)
	{
		y = pTop + (pHeight/2) - (height/2);
	}
	else if(alignment & ALIGN_BOTTOM)
	{
		y = pTop + pHeight - height;
	}

	return y + yoffset;
}

void GuiTooltip::SetEffect(int eff, int amount, int target)
{
	if(eff & EFFECT_FADE)
	{
		if(amount > 0)
			alphaDyn = 0;
		else if(amount < 0)
			alphaDyn = alpha;
		
		effects |= eff;
		effectAmount = amount;
		effectTarget = target;
	}
}

void GuiTooltip::ResetEffects()
{
	yoffsetDyn = 0;
	xoffsetDyn = 0;
	alphaDyn = -1;
	effects = EFFECT_NONE;
	effectAmount = 0;
	effectTarget = 0;
}

void GuiTooltip::UpdateEffects()
{
	if(effects & EFFECT_FADE)
	{
		alphaDyn += effectAmount;
		
		if(effectAmount < 0 && alphaDyn <= 0)
		{
			alphaDyn = 0;
			effects = 0; // shut off effect
			visible = false;
		}
		else if(effectAmount > 0 && alphaDyn >= alpha)
		{
			alphaDyn = alpha;
			effects = 0; // shut off effect
		}
	}
}

void GuiTooltip::Draw()
{
	if(parentElement)
	{
		if(parentElement->GetState() != STATE_SELECTED)
			selectedTimer.reset();
		
		if(parentElement->GetState() == STATE_DISABLED)
			return;
	}
	
	if(!visible || state == STATE_DISABLED)
		return;
	
	if(selectedTimer.elapsed() <= Settings.TooltipDelay)
		return;

	leftImage->Draw();
	tileImage->Draw();
	rightImage->Draw();
	if(text)
		text->Draw();

	UpdateEffects();
}
